Skip to content

[flags] land enableTrustedTypesIntegration#35816

Merged
rickhanlonii merged 1 commit intofacebook:mainfrom
rickhanlonii:rh/ff-trusted-types
Feb 25, 2026
Merged

[flags] land enableTrustedTypesIntegration#35816
rickhanlonii merged 1 commit intofacebook:mainfrom
rickhanlonii:rh/ff-trusted-types

Conversation

@rickhanlonii
Copy link
Member

Summary

This flag enables React's integration with the browser Trusted Types API.

The Trusted Types API is a browser security feature that helps prevent DOM-based XSS attacks. When a site enables Trusted Types enforcement via Content-Security-Policy: require-trusted-types-for 'script', the browser requires that values passed to DOM injection sinks (like innerHTML) are typed objects (TrustedHTML, TrustedScript, TrustedScriptURL) created through developer-defined sanitization policies, rather than raw strings.

What changed

Previously, React always coerced values to strings (via '' + value) before passing them to DOM APIs like setAttribute and innerHTML. This broke Trusted Types because it converted typed objects into plain strings, which the browser would then reject under Trusted Types enforcement.

React now passes values directly to DOM APIs without string coercion, preserving Trusted Types objects so the browser can validate them. This applies to dangerouslySetInnerHTML, all HTML and SVG attributes, and URL attributes (href, action, etc).

Before (broken)

Using Trusted Types with something likedangerouslySetInnerHTML would throw:

const sanitizer = trustedTypes.createPolicy('sanitizer', {
  createHTML: (input) => DOMPurify.sanitize(input),
});

function Comment({text}) {
  const clean = sanitizer.createHTML(text);
  // clean is a TrustedHTML object, but React would call '' + clean,
  // converting it back to a plain string before setting innerHTML.
  // Under Trusted Types enforcement, the browser rejects the string:
  //
  //   TypeError: Failed to set 'innerHTML' on 'Element':
  //   This document requires 'TrustedHTML' assignment.
  return <div dangerouslySetInnerHTML={{__html: clean}} />;
}

After (works)

React now passes the TrustedHTML object directly to the DOM without stringifying it:

 const policy = trustedTypes.createPolicy('sanitizer', {
   createHTML: (input) => DOMPurify.sanitize(input),
 });

 function Comment({text}) {
   // TrustedHTML objects are passed directly to innerHTML
   return <div dangerouslySetInnerHTML={{__html: policy.createHTML(text)}} />;
 }

 function UserProfile({bio}) {
   // String attribute values also preserve Trusted Types objects
   return <div data-bio={policy.createHTML(bio)} />;
 }

Non-breaking change

  • Sites using Trusted Types: React no longer breaks Trusted Types enforcement. TrustedHTML and TrustedScriptURL objects passed through React props are forwarded to the DOM without being stringified.
  • Sites not using Trusted Types: No behavior change. DOM APIs accept both strings and Trusted Types objects, so removing the explicit string coercion is functionally identical.

@meta-cla meta-cla bot added the CLA Signed label Feb 18, 2026
@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Feb 18, 2026
@rickhanlonii rickhanlonii changed the title [flags] land enableTrustedTypesIntegration [flags] land enableTrustedTypesIntegration Feb 18, 2026
@react-sizebot
Copy link

Comparing: 4842fbe...b9b92b9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 611.08 kB 611.04 kB = 108.02 kB 108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 677.02 kB 676.98 kB = 118.99 kB 118.97 kB
facebook-www/ReactDOM-prod.classic.js = 697.74 kB 697.18 kB = 122.68 kB 122.56 kB
facebook-www/ReactDOM-prod.modern.js = 688.05 kB 687.50 kB = 121.07 kB 120.94 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against b9b92b9

@jackpope jackpope self-requested a review February 18, 2026 21:29
@rickhanlonii rickhanlonii merged commit 074d96b into facebook:main Feb 25, 2026
235 checks passed
@rickhanlonii rickhanlonii deleted the rh/ff-trusted-types branch February 25, 2026 19:49
github-actions bot pushed a commit that referenced this pull request Feb 25, 2026
## Summary

This flag enables React's integration with the browser [Trusted Types
API](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API).

The Trusted Types API is a browser security feature that helps prevent
DOM-based XSS attacks. When a site enables Trusted Types enforcement via
`Content-Security-Policy: require-trusted-types-for 'script'`, the
browser requires that values passed to DOM injection sinks (like
`innerHTML`) are typed objects (`TrustedHTML`, `TrustedScript`,
`TrustedScriptURL`) created through developer-defined sanitization
policies, rather than raw strings.

 ### What changed

Previously, React always coerced values to strings (via `'' + value`)
before passing them to DOM APIs like `setAttribute` and `innerHTML`.
This broke Trusted Types because it converted typed objects into plain
strings, which the browser would then reject under Trusted Types
enforcement.

React now passes values directly to DOM APIs without string coercion,
preserving Trusted Types objects so the browser can validate them. This
applies to `dangerouslySetInnerHTML`, all HTML and SVG attributes, and
URL attributes (`href`, `action`, etc).

 ### Before (broken)

Using Trusted Types with something like`dangerouslySetInnerHTML` would
throw:

 ```js
 const sanitizer = trustedTypes.createPolicy('sanitizer', {
   createHTML: (input) => DOMPurify.sanitize(input),
 });

 function Comment({text}) {
   const clean = sanitizer.createHTML(text);
   // clean is a TrustedHTML object, but React would call '' + clean,
   // converting it back to a plain string before setting innerHTML.
   // Under Trusted Types enforcement, the browser rejects the string:
   //
   //   TypeError: Failed to set 'innerHTML' on 'Element':
   //   This document requires 'TrustedHTML' assignment.
   return <div dangerouslySetInnerHTML={{__html: clean}} />;
 }
 ```

### After (works)

React now passes the TrustedHTML object directly to the DOM without
stringifying it:

```js
 const policy = trustedTypes.createPolicy('sanitizer', {
   createHTML: (input) => DOMPurify.sanitize(input),
 });

 function Comment({text}) {
   // TrustedHTML objects are passed directly to innerHTML
   return <div dangerouslySetInnerHTML={{__html: policy.createHTML(text)}} />;
 }

 function UserProfile({bio}) {
   // String attribute values also preserve Trusted Types objects
   return <div data-bio={policy.createHTML(bio)} />;
 }
 ```

 ## Non-breaking change

 - Sites using Trusted Types: React no longer breaks Trusted Types enforcement. TrustedHTML and TrustedScriptURL objects passed through React props are forwarded to the DOM without being stringified.
 - Sites not using Trusted Types: No behavior change. DOM APIs accept both strings and Trusted Types objects, so removing the explicit string coercion is functionally identical.

DiffTrain build for [074d96b](074d96b)
github-actions bot pushed a commit that referenced this pull request Feb 25, 2026
## Summary

This flag enables React's integration with the browser [Trusted Types
API](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API).

The Trusted Types API is a browser security feature that helps prevent
DOM-based XSS attacks. When a site enables Trusted Types enforcement via
`Content-Security-Policy: require-trusted-types-for 'script'`, the
browser requires that values passed to DOM injection sinks (like
`innerHTML`) are typed objects (`TrustedHTML`, `TrustedScript`,
`TrustedScriptURL`) created through developer-defined sanitization
policies, rather than raw strings.

 ### What changed

Previously, React always coerced values to strings (via `'' + value`)
before passing them to DOM APIs like `setAttribute` and `innerHTML`.
This broke Trusted Types because it converted typed objects into plain
strings, which the browser would then reject under Trusted Types
enforcement.

React now passes values directly to DOM APIs without string coercion,
preserving Trusted Types objects so the browser can validate them. This
applies to `dangerouslySetInnerHTML`, all HTML and SVG attributes, and
URL attributes (`href`, `action`, etc).

 ### Before (broken)

Using Trusted Types with something like`dangerouslySetInnerHTML` would
throw:

 ```js
 const sanitizer = trustedTypes.createPolicy('sanitizer', {
   createHTML: (input) => DOMPurify.sanitize(input),
 });

 function Comment({text}) {
   const clean = sanitizer.createHTML(text);
   // clean is a TrustedHTML object, but React would call '' + clean,
   // converting it back to a plain string before setting innerHTML.
   // Under Trusted Types enforcement, the browser rejects the string:
   //
   //   TypeError: Failed to set 'innerHTML' on 'Element':
   //   This document requires 'TrustedHTML' assignment.
   return <div dangerouslySetInnerHTML={{__html: clean}} />;
 }
 ```

### After (works)

React now passes the TrustedHTML object directly to the DOM without
stringifying it:

```js
 const policy = trustedTypes.createPolicy('sanitizer', {
   createHTML: (input) => DOMPurify.sanitize(input),
 });

 function Comment({text}) {
   // TrustedHTML objects are passed directly to innerHTML
   return <div dangerouslySetInnerHTML={{__html: policy.createHTML(text)}} />;
 }

 function UserProfile({bio}) {
   // String attribute values also preserve Trusted Types objects
   return <div data-bio={policy.createHTML(bio)} />;
 }
 ```

 ## Non-breaking change

 - Sites using Trusted Types: React no longer breaks Trusted Types enforcement. TrustedHTML and TrustedScriptURL objects passed through React props are forwarded to the DOM without being stringified.
 - Sites not using Trusted Types: No behavior change. DOM APIs accept both strings and Trusted Types objects, so removing the explicit string coercion is functionally identical.

DiffTrain build for [074d96b](074d96b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants